/*
    更新内容：
    1.小兵按照几率赋予掉落装备
    2.增加攻击单位,attackUtilDeath,attackAll方法
*/
/*-----------------##############-------------------------------------##############--------------------------------------- */
/*---------------------------------------------构造函数-------------------------------------------------------------------- */

//攻击单位基类构造函数，小兵，野怪，都从这里继承
function attackUnit(opt) {
    //定义一个私有属性_hp，不向外暴露，只是由于内部调用，外部用hp去调用，和下面的Object.defineProperties配合
    this._hp = opt.hp;
    this.mp = opt.mp;
    this.hj = opt.hj;
    this.gjl = opt.gjl;
    //攻击单位被击杀后所值的金币
    this.gold = opt.gold;
    //被杀掉以后掉的物品
    this.bag = opt.bag || []
    this.wlfy = this.hj / 500 >= 1 ? 1 : this.hj / 500
    this.attack = function(enemy) {
        //在攻击之前首先判断对方英雄的血量，如果<=0就不进行攻击。
        if (enemy.hp <= 0) {
            console.log(`${enemy.name}已经挂了，不要在鞭尸了！`);
            //return以后的代码都不执行
            return
        }
        //调用打印口号函数
        if (this.type == "英雄") {
            this.say();
        }
        //每次攻击损失的血量，物理防御值约大损失的血量约小，当物理防御值趋近1时候，根本打不动
        var loss = this.gjl * (1 - enemy.wlfy)
            //对方英雄血量减少
        enemy.hp -= loss;
        console.log(`${this.name}攻击了${enemy.name}`);
        console.log(`${enemy.name}减少血量${loss}，剩余血量${enemy.hp}`);
        //如果对方被杀死呢
        if (enemy.hp <= 0) {
            console.log(`${enemy.name}挂了`);
            // 如果我是一个英雄而不是小兵
            if (this.type == "英雄") {
                // 我的钱增加数量为对方的价值，也就是对方的gold属性值
                this.money += enemy.gold;
                var context = this;
                if (enemy.type != "英雄") {
                    enemy.bag.forEach(function(item) {
                        var zbName = context.getZb(item);
                        console.error(`恭喜${context.name}获得神器${zbName}`)
                    })
                }
            }

        }
    }
    this.attackUntilDeath = function(enemy) {
        while (enemy.hp > 0) {
            this.attack(enemy)
        }
    }
    Object.defineProperties(this, {
        //配置对象的hp属性
        hp: {
            //当获取对象的hp时调用此函数
            get() {
                // console.log('hp get() is call');
                return this._hp
            },
            //单设置对象的hp时调用此函数，n就是等号右边的值
            //此方法的作用是让hp不能为负值，当设置hp为负值时候，会自动设置为0
            set(n) {
                if (n <= 0) { this._hp = 0 } else {
                    this._hp = n
                }
            }
        },
        //配置对象的name属性
        name: {
            //不可以写
            writable: false,
            // 不可以删除
            configurable: false,
            //name属性的默认值是形参传入的name
            value: opt.name
        }
    });

};

//小兵的构造函数
function smallSoldier(opt) {
    attackUnit.apply(this, arguments);
    //小兵独有属性
    this.type = "小兵";
    //按照几率赋予掉落装备
    this.randomZb = function() {
        //几率，
        var r = 0.1;
        if (Math.random() >= (1 - r)) {
            //按照几率把装备放进掉落物品栏
            this.bag.push(sxzl)
        }
    };
    //调用按照几率赋予掉落装备
    this.randomZb()
};

//野怪的构造函数
function jungleMonster(opt) {
    attackUnit.call(this, opt);
    //野怪独有属性
    this.type = "野怪"
}

//英雄构造函数
function Hero(opt) {

    attackUnit.call(this, opt);
    //英雄技能列表
    this.skills = opt.skills;
    //英雄口号列表
    this.kh = opt.kh;
    //英雄的钱
    this.money = opt.money;
    //装备列表
    this.zb = [];
    this.type = "英雄";
    //初始化防御值，护甲越高防御值越高，如护甲为50防御值为0.1

    //随机打印一个口号
    this.say = function() {
            //i是一个随机数
            var i = Math.round(Math.random() * (this.kh.length - 1))
            console.log(this.kh[i])
        }
        //攻击方法，对方英雄通过enemy参数传入

    //买装备
    this.buy = function(zb) {
            if (this.money >= zb.price) {
                this.getZb(zb);
                this.money -= zb.price
            }
        }
        //获得装备的方法
    this.getZb = function(zb) {
            //把装备放到zb属性里面的数组
            this.zb.push(zb);
            //通过迭代的方法赋值重点理解，得到装备以后英雄属性增加
            // this.gjl += zb.gjl;
            // this.hp += zb.hp;
            // this.mp += zb.mp
            for (var key in zb) {
                this[key] += zb[key]
            };
            this.skills = [...this.skills, ...zb.skills]
            return zb.name
        }
        //配置对象的属性

    this.attackAll = function(enemies) {
        var context = this;
        enemies.forEach(function(enemy) {
            context.attackUntilDeath(enemy);
        })
    }
};

//装备对象构造函数
function Zb(opt) {
    //初始化装备的参数
    this.hj = opt.hj;
    this.gjl = opt.gjl;
    this.hp = opt.hp;
    this.mp = opt.mp;
    this.name = opt.name;
    this.skills = opt.skills;
    this.price = opt.price;
    //配置装备的属性
    Object.defineProperties(this, {
        skills: {
            // skill这个属性将不会被for-in迭代
            enumerable: false
        },

        price: {
            // price这个属性将不会被for-in迭代
            enumerable: false
        },
        name: {
            // name这个属性将不会被for-in迭代
            enumerable: false
        }
    })
}


/*-----------------##############-------------------------------------##############--------------------------------------- */
/*------------------------------------英雄、小兵、野怪、装备配置参数------------------------------------------------- */
/*配置参数对象是一个参数，作为一个实参传入到构造函数，生成一个对象--------------------------------------------- */
//德玛西亚配置参数对象
var dmxyOpt = {
    name: "德玛西亚之力",
    kh: ['人在塔在', '德玛西亚万岁', '让你们见识德玛西亚的力量'],
    hp: 1000,
    mp: 0,
    gjl: 50,
    hj: 300,
    money: 3000,
    skills: ['沉默斩', '加护甲', '旋转陀螺', '大保健'],
    gold: 1000
}
var ysOpt = {
    name: "快乐风男",
    kh: ["面对疾风吧！", "哈萨key", "长路漫漫，唯剑作伴"],
    hp: 500,
    mp: 0,
    gjl: 80,
    hj: 100,
    money: 1000,
    skills: ["斩钢", "风墙", "e", "r"],
    gold: 1500
}
var zxOpt = {
    name: "菊花信",
    kh: ["长枪依在，菊花拿来", "一点寒芒先到，随后菊花就爆", "万军之中取你首级"],
    hp: 400,
    mp: 200,
    gjl: 90,
    hj: 150,
    money: 15000,
    skills: ["q", "w", "e", "r"],
    gold: 3000
}

//装备属性配置对象
var sxzlOpt = {
        name: '三相之力',
        hp: 100,
        mp: 100,
        gjl: 80,
        hj: 20,
        price: 2000,
        skills: ['攻击加成被动', '速度加成别动']
    }
    // 近程兵配置对象
var jcbOpt = {
        hp: 150,
        mp: 0,
        hj: 20,
        gjl: 10,
        gold: 20,
        name: "近程兵",
    }
    //远程兵配置对象
var ycbOpt = {
    hp: 100,
    mp: 0,
    hj: 15,
    gjl: 20,
    gold: 25,
    name: "远程兵",
}

var xlOpt = {
        hp: 10000,
        mp: 0,
        hj: 300,
        gjl: 200,
        gold: 10000,
        name: "小龙",
    }
    /*-----------------##############-------------------------------------##############--------------------------------------- */
    /*------------------------------------调用配置参数，向构造函数传入配置参数，生成对象------------------------------------ */

//英雄对象
var dmxy = new Hero(dmxyOpt)
var ys = new Hero(ysOpt)
var zx = new Hero(zxOpt)
    //装备对象
var sxzl = new Zb(sxzlOpt)
    //批量创建小兵对象，封装一个函数，传入数字，和一个配置参数对象，生成一个包含小兵对象的数组
function createSoldiers(num, opt) {
    var soldiersArray = [];
    for (var i = 1; i <= num; i++) {
        var s = new smallSoldier(opt);
        soldiersArray.push(s)
    }
    return soldiersArray
}
//生成一个带有10个近程兵的数组
var jcbArray = createSoldiers(50, jcbOpt)
    //生成一个带有20个远程兵的数组
var ycbArray = createSoldiers(20, ycbOpt)

//生成单个近程兵
var jcb = new smallSoldier(jcbOpt);
//生成单个远程兵
var ycb = new smallSoldier(ycbOpt);
//生成一个野怪
var xl = new jungleMonster(xlOpt);